package com.fin.zw.aiqas.service;


import com.fin.zw.aiqas.entity.*;
import com.fin.zw.aiqas.enums.UserStatus;
import com.fin.zw.aiqas.model.request.UserInfoRequest;
import com.fin.zw.aiqas.model.response.DepartmentResponse;
import com.fin.zw.aiqas.model.response.DeptAndUsersResponse;
import com.fin.zw.aiqas.model.response.UserInfoResponse;
import com.fin.zw.aiqas.model.session.SessionModel;
import com.fin.zw.aiqas.repository.*;
import com.fin.zw.aiqas.util.BadRequestException;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.*;


@Service("userInfoService")
public class UserInfoService {
    private static final Logger log = LoggerFactory.getLogger(UserInfoService.class);

    @Autowired
    private UserInfoRepository userInfoRepository;

    @Autowired
    private AccountRepository accountRepository;

    @Autowired
    private RoleInfoRepository roleInfoRepository;

    @Autowired
    private DepartmentRepository departmentRepository;

    @Autowired
    private SystemParamRepository systemParamRepository;
    /**
     * 用户的创建
     * @param request
     */
    public void createUserInfo(UserInfoRequest request, SessionModel session){
        UserInfo userInfo = new UserInfo();
        BeanUtils.copyProperties(request,userInfo);
        Account account = createAccount(request.getAccountName());
        userInfo.setAccount(account);
        if (request.getDepartId() != null) {
            Department department = departmentRepository.findById(request.getDepartId()).orElseThrow(() -> new BadRequestException("", "找不到对应的机构信息"));
            userInfo.setDepartment(department);
        }
        userInfo.setCreateTime(new Date());
        userInfo.setOperatorId(session.getUserId());
        userInfo.setOperatorRealName(session.getUserName());
        userInfoRepository.save(userInfo);
    }

    /**
     * 创建账号
     * @param accountName
     */
    public Account createAccount(String accountName){
        Iterator<Account> iterator = accountRepository.findAll(QAccount.account.name.eq(accountName)).iterator();
        if(iterator.hasNext()){
            throw new BadRequestException("", "该账号已经被占用...");
        }
        Account account = new Account();
        account.setName(accountName);
        account.setUserStatus(UserStatus.USER_START);
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String pwd = passwordEncoder.encode("888888");
        account.setPassword(pwd);
        account = accountRepository.save(account);
        return account;
    }

    /**
     * 用户信息的更新
     * @param request
     */
    public void updateUserInfo(UserInfoRequest request, SessionModel   session){
        UserInfo userInfo = userInfoRepository.findById(request.getId()).orElseThrow(() -> new BadRequestException("", "用户信息不存在"));
        BooleanBuilder builder = new BooleanBuilder();
        QAccount qAccount = QAccount.account;
        builder.and(qAccount.name.eq(request.getAccountName()));
        builder.and(qAccount.id.ne(request.getAccountId()));
        Optional<Account> one = accountRepository.findOne(builder);
        if (one.isPresent()) {
            throw new BadRequestException("", "此用户名已存在");
        }
        Account account = userInfo.getAccount();
        if (request.getRoleIds() != null && !request.getRoleIds().isEmpty()) {
            Iterator<RoleInfo> infoIterator = roleInfoRepository.findAll(QRoleInfo.roleInfo.id.in(request.getRoleIds())).iterator();
            Set<RoleInfo> set = new HashSet<>(Lists.newArrayList(infoIterator));
            account.setRoleInfoSet(set);
        }
        account.setName(request.getAccountName());
        accountRepository.save(account);
        userInfo.setName(request.getName());
        userInfo.setStatus(request.getStatus());
        userInfo.setPhone(request.getPhone());
        userInfo.setSex(request.getSex());
        userInfo.setAccount(account);
        if (null != request.getDepartId()) {
            Department department = departmentRepository.findById(request.getDepartId()).orElseThrow(() -> new BadRequestException("", "找不到对应的机构信息"));
            userInfo.setDepartment(department);
        }
        userInfo.setUpdateRealName(session.getUserName());
        userInfo.setUpdateUserId(session.getUserId());
        userInfo.setUpdateTime(new Date());
        userInfoRepository.save(userInfo);
    }


    /**
     * 查询用户信息（分页）
     * @param pageable
     * @return
     */
    public Page<UserInfoResponse> getUserInfoAll(UserInfoRequest request, Pageable pageable, SessionModel sessionModel) {
        BooleanBuilder builder = new BooleanBuilder();
        QUserInfo qUserInfo = QUserInfo.userInfo;
        if (request.getDepartId() != null) {
            Department department = departmentRepository.findById(request.getDepartId()).orElseThrow(() -> new BadRequestException("", "找不到对应的机构信息"));
            builder.and(qUserInfo.department.code.contains(department.getCode()));
        }
        if (StringUtils.isNotBlank(request.getDeptCode())) {
            builder.and(qUserInfo.department.code.contains(request.getDeptCode()));
        } else {
            builder.and(qUserInfo.department.code.contains(sessionModel.getDepartCode()));
        }
        if(StringUtils.isNotEmpty(request.getName())){
            builder.and(qUserInfo.name.like("%".concat(request.getName()).concat("%")));
        }
        if(StringUtils.isNotEmpty(request.getAccountName())){
            builder.and(qUserInfo.account.name.like("%".concat(request.getAccountName()).concat("%")));
        }
        if(StringUtils.isNotEmpty(request.getPhone())){
            builder.and(qUserInfo.phone.eq(request.getPhone()));
        }
        if(request.getStatus() != null){
            builder.and(qUserInfo.status.eq(request.getStatus()));
        }
        Page<UserInfo> userInfoPage = userInfoRepository.findAll(builder,pageable);
        Page<UserInfoResponse> page = userInfoPage.map(userInfo -> {
            UserInfoResponse response = new UserInfoResponse();
            BeanUtils.copyProperties(userInfo, response);
            if (Objects.nonNull(userInfo.getDepartment())) {
                DepartmentResponse departmentResponse = new DepartmentResponse();
                BeanUtils.copyProperties(userInfo.getDepartment(), departmentResponse);
                if (Objects.nonNull(userInfo.getDepartment().getParent())) {
                    departmentResponse.setParent(userInfo.getDepartment().getParent().getId());
                }
                response.setDepartment(departmentResponse);
            }
            if(Objects.nonNull(userInfo.getAccount())) {
                Account account = userInfo.getAccount();
                response.setAccountId(account.getId());
                response.setAccountName(account.getName());
                response.setAccountStatus(account.getUserStatus());
                response.setRoleInfoSet(account.getRoleInfoSet());
            }
            return response;
        });
        return page;
    }


    /**
     * 根据角色查询用户
     *
     * @param pageable
     * @param roleId
     * @Param accountName 账号
     * @Param userName 用户名称
     * @return
     */
    public Page<UserInfoResponse> getListByRoleId(Pageable pageable, Long roleId, String accountName, String userName) {
        Optional<RoleInfo> optional = roleInfoRepository.findById(roleId);
        if (!optional.isPresent()) {
            throw new BadRequestException("", "角色信息不存在");
        }
        RoleInfo roleInfo = optional.get();
        BooleanBuilder builder = new BooleanBuilder();
        QUserInfo qUserInfo = QUserInfo.userInfo;
        builder.and(qUserInfo.account.roleInfoSet.contains(roleInfo));
        if (StringUtils.isNotBlank(accountName)) {
            builder.and(qUserInfo.account.name.eq(accountName));
        }
        if (StringUtils.isNotBlank(userName)) {
            builder.and(qUserInfo.name.eq(userName));
        }
        Page<UserInfo> userInfoPage = userInfoRepository.findAll(builder, pageable);
        Page<UserInfoResponse> page = userInfoPage.map(userInfo -> {
            UserInfoResponse response = new UserInfoResponse();
            BeanUtils.copyProperties(userInfo, response);
            if (Objects.nonNull(userInfo.getDepartment())) {
                DepartmentResponse departmentResponse = new DepartmentResponse();
                BeanUtils.copyProperties(userInfo.getDepartment(), departmentResponse);
                if (Objects.nonNull(userInfo.getDepartment().getParent())) {
                    departmentResponse.setParent(userInfo.getDepartment().getParent().getId());
                }
                response.setDepartment(departmentResponse);
            }
            if (Objects.nonNull(userInfo.getAccount())) {
                Account account = userInfo.getAccount();
                response.setAccountId(account.getId());
                response.setAccountName(account.getName());
                response.setAccountStatus(account.getUserStatus());
                response.setRoleInfoSet(account.getRoleInfoSet());
            }
            return response;
        });
        return page;
    }

    /**
     * 查询全部人员，不分页
     * @param request
     * @return
     */
    public List<UserInfoResponse> getAllUser(UserInfoRequest request){
        List<UserInfoResponse> listUsers = new ArrayList<>();
        BooleanBuilder builder = new BooleanBuilder();
        QUserInfo qUserInfo = QUserInfo.userInfo;
        if(null != request.getDepartId()){
            Department department = departmentRepository.findById(request.getDepartId()).orElseThrow(() -> new BadRequestException("", "找不到对应的机构信息"));
            builder.and(qUserInfo.department.code.contains(department.getCode()));
        }
        if(StringUtils.isNotEmpty(request.getName())){
            builder.and(qUserInfo.name.like("%".concat(request.getName()).concat("%")));
        }
        if(StringUtils.isNotEmpty(request.getPhone())){
            builder.and(qUserInfo.phone.eq(request.getPhone()));
        }
        Iterator<UserInfo> iterator = userInfoRepository.findAll(builder).iterator();
        while (iterator.hasNext()){
            UserInfo next = iterator.next();
            UserInfoResponse  userInfoResponse = new UserInfoResponse();
            userInfoResponse.setId(next.getId());
            userInfoResponse.setName(next.getName());
            listUsers.add(userInfoResponse);
        }
        return listUsers;
    }

    /**
     * 查询每个部门的所有人
     *
     * @return
     */
    public List<DeptAndUsersResponse> fetchAllDeptAndUserInfos() {
        List<DeptAndUsersResponse> deptAndUsersResponseList = new ArrayList<>();
        List<UserInfo> userInfoList = userInfoRepository.findAll();
        List<Department> departmentList = departmentRepository.findAll();
        departmentList.forEach(department -> {
            DeptAndUsersResponse response = new DeptAndUsersResponse();
            response.setDeptId(department.getId());
            response.setDeptName(department.getName());
            List<UserInfoResponse> userInfoToDeptList = new ArrayList<>();
            userInfoList.forEach(userInfo -> {
                if (userInfo.getDepartment().getId().equals(department.getId())) {
                    UserInfoResponse userInfoResponse = new UserInfoResponse();
                    BeanUtils.copyProperties(userInfo, userInfoResponse);
                    userInfoToDeptList.add(userInfoResponse);
                }
            });
            response.setUserInfoResponseList(userInfoToDeptList);
            deptAndUsersResponseList.add(response);
        });
        return deptAndUsersResponseList;
    }

    /**
     * 查询每个部门拥有复核权限的所有人
     *
     * @return
     */
    public List<DeptAndUsersResponse> fetchDeptAndUsersByRole() {
        //查询配置表  type = REVIEWUSER
        List<Long> roleIDs = new ArrayList<>();
        QSystemParam qSystemParam = QSystemParam.systemParam;
        Iterator<SystemParam> paramIterator = systemParamRepository.findAll(new BooleanBuilder().and(qSystemParam.type.eq("REVIEWUSER"))).iterator();
        while (paramIterator.hasNext()) {
            roleIDs.add(Long.valueOf(paramIterator.next().getValue()));
        }
        if (!roleIDs.isEmpty()) {
            //返回集合
            List<DeptAndUsersResponse> deptAndUsersResponseList = new ArrayList<>();
            //所有的有复核权限的人
            Set<UserInfo> userInfoSet = new HashSet<>();
            QRoleInfo qRoleInfo = QRoleInfo.roleInfo;
            Iterator<RoleInfo> roleInfoIterator = roleInfoRepository.findAll(qRoleInfo.id.in(roleIDs)).iterator();
            if (!roleInfoIterator.hasNext()) {
                log.info("UserInfoService 的 fetchDeptAndUsersByRole方法 根据配置表 REVIEWUSER 没有查到对应角色信息");
                throw new BadRequestException("", "查询复核人员失败");
            }
            while (roleInfoIterator.hasNext()) {
                QUserInfo qUserInfo = QUserInfo.userInfo;
                Iterator<UserInfo> iterator = userInfoRepository.findAll(qUserInfo.account.roleInfoSet.contains(roleInfoIterator.next())).iterator();
                HashSet<UserInfo> userInfoHashSet = Sets.newHashSet(iterator);
                if (userInfoHashSet.isEmpty()) {
                    log.info("UserInfoService 的 fetchDeptAndUsersByRole 方法根据角色没有查到对应人员");
                    throw new BadRequestException("", "查询复核人员失败");
                }
                userInfoSet.addAll(userInfoHashSet);
            }
            List<Department> departmentList = departmentRepository.findAll();
            departmentList.forEach(department -> {
                DeptAndUsersResponse response = new DeptAndUsersResponse();
                response.setDeptId(department.getId());
                response.setDeptName(department.getName());
                List<UserInfoResponse> userInfoToDeptList = new ArrayList<>();
                userInfoSet.forEach(userInfo -> {
                    if (userInfo.getDepartment().getId().equals(department.getId())) {
                        UserInfoResponse userInfoResponse = new UserInfoResponse();
                        BeanUtils.copyProperties(userInfo, userInfoResponse);
                        userInfoToDeptList.add(userInfoResponse);
                    }
                });
                if (!userInfoToDeptList.isEmpty()) {
                    response.setUserInfoResponseList(userInfoToDeptList);
                    deptAndUsersResponseList.add(response);
                }
            });
            return deptAndUsersResponseList;
        } else {
            log.info("UserInfoService 的 fetchDeptAndUsersByRole 方法查询时在配置表system_param中没有查到配置信息");
            return null;
        }
    }
}
